package vim.meet.javassist;

import javassist.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.lang.instrument.Instrumentation;
import java.security.ProtectionDomain;

public class ReplaceArrayListToStringClassFileTransformer implements ClassFileTransformer {
    
    private Logger logger = LoggerFactory.getLogger(ReplaceArrayListToStringClassFileTransformer.class);

    private final String src = "public String toString() {Iterator<E> it = iterator(); if (! it.hasNext()) return \"{{}}\"; StringBuilder sb = new StringBuilder(); sb.append('{{'); for (;;) {E e = it.next(); sb.append(e == this ? \"(this Collection)\" : e); if (! it.hasNext()) return sb.append('}}').toString(); sb.append(',').append(' '); } }";
    @Override
    public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined,
            ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
//      全限定名称转换: sun/launcher/LauncherHelper -->sun.launcher.LauncherHelper
        logger.info(className);
      if (className != null && className.indexOf("/") != -1) {
          className = className.replaceAll("/", ".");
      }
        if (className.endsWith("ArrayList")) {
            try {
                logger.info(className);
                CtClass cc = ClassPool.getDefault().get(className);
                CtMethod toString = CtMethod.make(src, cc);
                cc.addMethod(toString);
                try {
                    return cc.toBytecode();
                } catch (IOException e) {
                    logger.error(e.getMessage(), e);
                } catch (CannotCompileException e) {
                    logger.error(e.getMessage(), e);
                }
            } catch (NotFoundException e) {
                logger.error(e.getMessage(), e);
            } catch (CannotCompileException e) {
                logger.error(e.getMessage(), e);
            }
        }
        return null;
    }
    
    public static void premain(String options, Instrumentation instrumentation) {
        instrumentation.addTransformer(new ReplaceArrayListToStringClassFileTransformer());
    }
    
    public static void main(String[] args) {
        
    }
    
}
